/*
*  Copyright 2019-2020 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package me.zhengjie.business.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.business.domain.Order;
import me.zhengjie.business.domain.Snry;
import me.zhengjie.business.domain.Zhsq;
import me.zhengjie.business.domain.vo.*;
import me.zhengjie.business.repository.SnryRepository;
import me.zhengjie.business.repository.ZhsqRepository;
import me.zhengjie.business.service.ZhsqService;
import me.zhengjie.business.service.dto.*;
import me.zhengjie.config.DebugProperties;
import me.zhengjie.inter.service.MpZhsqService;
import me.zhengjie.utils.*;
import lombok.RequiredArgsConstructor;
import me.zhengjie.business.repository.OrderRepository;
import me.zhengjie.business.service.OrderService;
import me.zhengjie.business.service.mapstruct.OrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.hutool.core.util.IdUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.io.IOException;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.StoredProcedureQuery;
import javax.servlet.http.HttpServletResponse;

/**
* @website https://el-admin.vip
* @description 服务实现
* @author xiahongbo
* @date 2022-08-03
**/
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {

    private final OrderRepository orderRepository;
    private final OrderMapper orderMapper;
    private final ZhsqService zhsqService;
    private final MpZhsqService mpZhsqService;
    private final ZhsqRepository zhsqRepository;
    private final SnryRepository snryRepository;

    @Autowired
    private EntityManager entityManager;

    @Override
    public Page<Order> queryAll(OrderQueryCriteria criteria, Pageable pageable){
        Page<Order> page = orderRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return page;
    }

    @Override
    public List<OrderDto> queryAll(OrderQueryCriteria criteria){
        return orderMapper.toDto(orderRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }
    @Override
    public Page<Order>  listDisability(OrderQueryCriteria criteria, Pageable pageable){
        long userId = SecurityUtils.getCurrentUserId();
        log.info("userId {}", userId);
        /*
        ZhsqQueryCriteria zhsqQueryCriteria = new ZhsqQueryCriteria();
        zhsqQueryCriteria.setBisUserId(userId);
        List<ZhsqDto> list = zhsqService.queryAll(zhsqQueryCriteria);
        log.info("list {}", list);
        List<Long> ids = new ArrayList<>();
        for(ZhsqDto zhsqDto : list){
            ids.add(zhsqDto.getBisZhsqId());
        }
        log.info("ids {}", ids);
        if(ids.size() == 0) {
            ids.add(0l);
        }
        */
        List<Long> ids = mpZhsqService.queryZhidsByUserId(userId);
        if(ids == null || ids.size() == 0) {
            ids.add(0l);
        }
        criteria.setBisOrderZhids(ids);
    //    return orderRepository.queryByBisOrderZhidInAndBisOrderZt(ids,criteria.getBisOrderZt(),pageable);
        Page<Order> page = orderRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return page;
    }

    @Override
    @Transactional
    public OrderDto findById(String bisOrderId) {
        Order order = orderRepository.findById(bisOrderId).orElseGet(Order::new);
        ValidationUtil.isNull(order.getBisOrderId(),"Order","bisOrderId",bisOrderId);
        return orderMapper.toDto(order);
    }

    @Override
    @Transactional
    public void updateZt(Order resources) {
        System.out.println("休眠前");
        // 休眠1000毫秒（即1秒）
/*        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/
        System.out.println("休眠后");
        log.info("updateZt:生成费用明细存储过程");
        if(!DebugProperties.debug) {
            log.info("生成费用明细存储过程 开始 :{}", resources);

            /**
             * StoredProcedureQuery 创建存储过程仓库
             * createStoredProcedureQuery（name） name 时过程名
             * registerStoredProcedureParameter表示存储过程中注册的参数
             * ParameterMode 参数
             */
            StoredProcedureQuery storedProcedureQuery = this.entityManager.createNamedStoredProcedureQuery("makeFymx");

            /**
             * 设置传入参数值
             */
            storedProcedureQuery.setParameter("IR_FWLX",resources.getBisOrderServiceType());
            storedProcedureQuery.setParameter("IR_ORDER_ID",resources.getBisOrderId());
            storedProcedureQuery.setParameter("IR_USER_ID",String.valueOf(SecurityUtils.getCurrentUserId()));
            storedProcedureQuery.setParameter("IR_ZHID",String.valueOf(resources.getBisOrderZhid()));
            /**
             * 获取结果出参
             */
            storedProcedureQuery.execute();
            int code = (int) storedProcedureQuery.getOutputParameterValue("OR_APPCODE");
            String msg = (String) storedProcedureQuery.getOutputParameterValue("OR_MESSAGE");

            log.info("生成费用明细存储过程 结束 :code:{}，msg:{}", code, msg);


            if(code == 1) {

                Object obj = orderRepository.query2210(resources.getBisOrderId(), resources.getBisOrderServiceType());
                Object[] arr = (Object[]) obj;
                String grbh = (String)arr[0];
                String ybc2210 = (String)arr[1];

                log.info("生成费用明细存储过程-["+resources.getBisOrderId()+"]-就诊登记执行核心库同步 个人编号 :{}" + grbh);
                log.info("生成费用明细存储过程-["+resources.getBisOrderId()+"]-就诊登记执行核心库同步 登记串 :{}" + ybc2210);
                log.info("生成费用明细存储过程-["+resources.getBisOrderId()+"]-就诊登记执行核心库同步 开始 :{}");
                StoredProcedureQuery siInterfaceProcedureQuery = this.entityManager.createNamedStoredProcedureQuery("siInterface");

                siInterfaceProcedureQuery.setParameter("PRM_入参", ybc2210);
                siInterfaceProcedureQuery.setParameter("PRM_卡串或者个人编号", grbh);

                siInterfaceProcedureQuery.execute();
                code = (int) siInterfaceProcedureQuery.getOutputParameterValue("PRM_APPCODE");
                msg = (String) siInterfaceProcedureQuery.getOutputParameterValue("PRM_出参");

                log.info("生成费用明细存储过程-["+resources.getBisOrderId()+"]-就诊登记执行核心库同步 结束 :code:{}，msg:{}", code, msg);
            }
        }
/*
        Object obj1 = orderRepository.queryOrderHlstartById(resources.getBisOrderId());
        String[] arr1 = (String[]) obj1;
        String starttime = (String)arr1[0];

        Date startDate = DateTimeUtil.parse(starttime, DateTimeUtil.DEFAULT_DATETIME_FORMAT);
        Date endDate = DateUtil.date();
        long sc = DateTimeUtil.diffMinutes(endDate, startDate);

        resources.setBisOrderHlend(endDate);
        resources.setBisOrderHlsc(String.valueOf(sc));
        orderRepository.save(order);*/
        Order order = orderRepository.findById(resources.getBisOrderId()).orElseGet(Order::new);

        Date startDate = order.getBisOrderHlstart();
        Date endDate = DateUtil.date();
        long sc = DateTimeUtil.diffMinutes(endDate, startDate);

        order.setBisOrderZt(resources.getBisOrderZt());
        order.setBisOrderHlend(endDate);
        order.setBisOrderHlsc(String.valueOf(sc));
        orderRepository.save(order);
        log.info("updateZt:12121212121212121");
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderDto create(Order resources) {
        resources.setBisOrderId(IdUtil.simpleUUID()); 
        return orderMapper.toDto(orderRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Order resources) {
        Order order = orderRepository.findById(resources.getBisOrderId()).orElseGet(Order::new);
        ValidationUtil.isNull( order.getBisOrderId(),"Order","id",resources.getBisOrderId());
        order.copy(resources);
        orderRepository.save(order);
    }

    @Override
    public void deleteAll(String[] ids) {
        for (String bisOrderId : ids) {
            orderRepository.deleteById(bisOrderId);
        }
    }

    @Override
    public void download(List<OrderDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (OrderDto order : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void makeJzdj(Order resources) {


        if(!DebugProperties.debug) {
            log.info("开始护理-["+resources.getBisOrderId()+"]-生成就诊登记存储过程 开始 :{}", resources);

            /**
             * StoredProcedureQuery 创建存储过程仓库
             * createStoredProcedureQuery（name） name 时过程名
             * registerStoredProcedureParameter表示存储过程中注册的参数
             * ParameterMode 参数
             */
            StoredProcedureQuery storedProcedureQuery = this.entityManager.createNamedStoredProcedureQuery("makeJzdj");

            /**
             * 设置传入参数值
             */
            storedProcedureQuery.setParameter("IR_FWLX",resources.getBisOrderServiceType());
            storedProcedureQuery.setParameter("IR_ORDER_ID",resources.getBisOrderId());
            storedProcedureQuery.setParameter("IR_USER_ID", String.valueOf(SecurityUtils.getCurrentUserId()));
            storedProcedureQuery.setParameter("IR_ZHID", String.valueOf(resources.getBisOrderZhid()));
            /**
             * 获取结果出参
             */
            storedProcedureQuery.execute();
            int code = (int) storedProcedureQuery.getOutputParameterValue("OR_APPCODE");
            String msg = (String) storedProcedureQuery.getOutputParameterValue("OR_MESSAGE");

            log.info("开始护理-["+resources.getBisOrderId()+"]-生成就诊登记存储过程 结束 :code:{}，msg:{}", code, msg);

        }

        Order order = orderRepository.findById(resources.getBisOrderId()).orElseGet(Order::new);
        order.setBisOrderHlstart(DateUtil.date());
        order.setBisOrderZt("3");
        order.setBisOrderJd(resources.getBisOrderJd());
        order.setBisOrderWd(resources.getBisOrderWd());
        orderRepository.save(order);
    }

    @Override
    public void test(String orderID) {

        Object obj = orderRepository.query2210(orderID,"");
        log.info("-就诊登记执行核心库同步 {} " + obj);
        Object[] arr = (Object[]) obj;
        log.info("-就诊登记执行核心库同步 {} " + arr);
        log.info("-就诊登记执行核心库同步 {} " + arr[0]);
        log.info("-就诊登记执行核心库同步 {} " + arr[1]);
    }

    @Override
    public Integer queryVerifyPerson(String orderId) {
        return orderRepository.queryVerifyPerson(orderId);
    }


    /**
     * 根据月份，查询每月的订单数量
     * @param month
     * @return
     */
    @Override
    public List<JSONObject> groupByHlry2Count(String month) {

        month = month.substring(0, 7);

        List<Object> list = orderRepository.groupByHlry2Count(month);
        List<JSONObject> vos = new ArrayList<>();
        for (Object obj : list) {
            Object[] arr = (Object[]) obj;

            JSONObject vo = new JSONObject();
            vo.put("content", ((BigDecimal)arr[0]).toPlainString());
            vo.put("hlrq", (String)arr[1]);
            vos.add(vo);
        }
        return vos;
    }

    @Override
    public Map<String, Object> OrderCntList(String hlrq, Pageable pageable) {
        Page<Object> page =  orderRepository.queryOrderCnt(hlrq, pageable);
        log.info("page: {} ", page);
        log.info("page.getContent(): {} ", page.getContent());
        List<Object> list = page.getContent();
        List<OrderCntVo> rsList = new ArrayList<>();
        for (Object obj: list) {
            Object[] arr = (Object[])obj;
            OrderCntVo orderCntVo = new OrderCntVo();
            log.info("arr: {} ", arr[0]);
            log.info("arr: {} ", arr[1]);
            orderCntVo.setQymc((String)arr[0]);
            orderCntVo.setCnt(((BigDecimal)arr[1]).longValue());
            rsList.add(orderCntVo);
        }
        return PageUtil.toPage(rsList, page.getTotalElements());
    }

    @Override
    public Map<String, Object> queryAllOrderList(OrderQueryCriteria criteria, Pageable pageable) {
        Page<OrderVo> page =  orderRepository.queryAllOrderList(criteria.getJgxx(), criteria.getRyxx(), criteria.getDdzt(), criteria.getHlrq(), criteria.getSbgs(), pageable);
        return PageUtil.toPage(page);
    }

    @Override
    public List<OrderVo> queryAllOrderList(OrderQueryCriteria criteria) {
        return orderRepository.queryAllOrderList(criteria.getJgxx(), criteria.getRyxx(), criteria.getDdzt(), criteria.getHlrq(), criteria.getSbgs());
    }

    @Override
    public void downloadAllOrderVo(List<OrderVo> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (OrderVo project : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("订单状态", project.getOrderZt());
            map.put("定点编码", project.getAkb020());
            map.put("居家名称", project.getAkb021());
            map.put("姓名", project.getXm());
            map.put("身份证", project.getSfz());
            map.put("待遇开始日期", project.getDyksrq());
            map.put("待遇结束日期", project.getDyjsrq());
            map.put("申请状态", project.getZhzt());
            map.put("护理日期", project.getHlrq());
            map.put("护理员姓名", project.getHlyxm());
            map.put("计划起始", project.getJhStartTime());
            map.put("计划结束", project.getJhEndTime());
            map.put("护理开始时间", project.getHlStartTime());
            map.put("护理结束时间", project.getHlEndTime());
            map.put("结算时间", project.getAae036());
            map.put("医疗总费用", project.getAkc264());
            map.put("个人现金", project.getAkc261());
            map.put("统筹支付", project.getAkc260());
            map.put("联系电话", project.getLxdh());
            map.put("监护人姓名", project.getJhrxm());
            map.put("监护人电话", project.getJhrdh());
            map.put("护理地址", project.getHldz());
            map.put("护理详址", project.getHldz_xxdz());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public Page<OrderWxVo> queryAllOrderWxVoList(OrderQueryCriteria criteria, Pageable pageable) {
        Page<OrderWxVo> page =  orderRepository.queryAllOrderWxVoList(criteria.getBisOrderZts(), criteria.getBisOrderHlyId(), criteria.getBisZhsqSnryXm(), pageable);
        return page;
    }

    @Override
    public Object queryAllOrderWxVoList(OrderQueryCriteria criteria, int[] startEnd, Pageable pageable) {
        String tempSql =  "select bis_order_id, " +
                "       bis_order_zhid, " +
                "       bis_order_faid, " +
                "       bis_order_hlrq, " +
                "       bis_order_hly_id, " +
                "       bis_order_hly_name, " +
                "       bis_order_service_type, " +
                "       bis_order_start_time, " +
                "       bis_order_end_time, " +
                "       bis_order_jd, " +
                "       bis_order_wd, " +
                "       bis_order_zt, " +
                "       bis_order_hlstart, " +
                "       bis_order_hlend, " +
                "       bis_order_hlsc, " +
                "       bis_order_pjzt, " +
                "       bis_order_xjzt, " +
                "       r2.bis_zhsq_snry_xm," +
                "       r2.bis_zhsq_snry_sfz " +
                "  from bis_order r1, bis_zhsq r2 " +
                "  where r1.bis_order_zhid = r2.bis_zhsq_id ";

        // 使用预编译防止sql注入
        String sql = "select * from ( " + tempSql + "  ) n where 1=1 ";

        String conditionSql1 = "";
        if(true) {
            conditionSql1 += " and n.bis_order_zt in :zt ";
        }
        if(true) {
            conditionSql1 += " and n.bis_order_hly_id=:hlyid ";
        }
        if(!StringUtils.isEmpty(criteria.getBisZhsqSnryXm())) {
            conditionSql1 += " and n.bis_zhsq_snry_xm like :xm ";
        }

        sql += conditionSql1 + " order by n.bis_order_hlrq desc";

        Query query = entityManager.createNativeQuery(sql);
        query.setFirstResult(startEnd[0]);
        query.setMaxResults(startEnd[1] - startEnd[0]);

        if(true) {
            query.setParameter("zt", criteria.getBisOrderZts());
        }
        if(true) {
            query.setParameter("hlyid", criteria.getBisOrderHlyId());
        }
        if(!StringUtils.isEmpty(criteria.getBisZhsqSnryXm())) {
            query.setParameter("xm", "%" + criteria.getBisZhsqSnryXm() + "%");
        }
        List result = query.getResultList();
        List<OrderWxVo> hljgDspVos = new ArrayList<>();
        for (Object obj : result) {
            Object[] arr = (Object[]) obj;
            Zhsq zhsq = new Zhsq();
            zhsq.setBisZhsqSnryXm(arr[17].toString());
            zhsq.setBisZhsqSnrySfz(arr[18].toString());
            OrderWxVo vo = new OrderWxVo();
            vo.setBisOrderId(arr[0]);
            vo.setBisOrderZhid(arr[1]);
            vo.setBisOrderFaid(arr[2]);
            vo.setBisOrderHlrq(arr[3]);
            vo.setBisOrderHlyId(arr[4]);
            vo.setBisOrderHlyName(arr[5]);
            vo.setBisOrderServiceType(arr[6]);
            vo.setBisOrderStartTime(arr[7]);
            vo.setBisOrderEndTime(arr[8]);
            vo.setBisOrderJd(arr[9]);
            vo.setBisOrderWd(arr[10]);
            vo.setBisOrderZt(arr[11]);
            vo.setBisOrderHlstart(arr[12]);
            vo.setBisOrderHlend(arr[13]);
            vo.setBisOrderHlsc(arr[14]);
            vo.setBisOrderPjzt(arr[15]);
            vo.setBisOrderXjzt(arr[16]);
            vo.setZhsq(zhsq);
            hljgDspVos.add(vo);
        }
        String countSql = "select count(1) from ( " + tempSql + "  ) n where 1=1 ";
        String conditionSql2 = "";
        if(true) {
            conditionSql2 += " and n.bis_order_zt in :zt ";
        }
        if(true) {
            conditionSql2 += " and n.bis_order_hly_id=:hlyid ";
        }
        if(!StringUtils.isEmpty(criteria.getBisZhsqSnryXm())) {
            conditionSql2 += " and n.bis_zhsq_snry_xm like :xm ";
        }
        countSql += conditionSql2;
        Query queryCount = entityManager.createNativeQuery(countSql);

        if(true) {
            queryCount.setParameter("zt", criteria.getBisOrderZts());
        }
        if(true) {
            queryCount.setParameter("hlyid", criteria.getBisOrderHlyId());
        }
        if(!StringUtils.isEmpty(criteria.getBisZhsqSnryXm())) {
            queryCount.setParameter("xm", "%" + criteria.getBisZhsqSnryXm() + "%");
        }
        Object totalElements = queryCount.getSingleResult();
        Map<String,Object> map = new LinkedHashMap<>(2);
        map.put("content",hljgDspVos);
        map.put("total",totalElements);
        map.put("totalElements",totalElements);
        map.put("pageable",pageable);
        return map;
    }

    @Override
    public Object getZhJWDtest(String bisOrderZhid, String ordjd, String ordwd) {
        Optional<Zhsq> byId = zhsqRepository.findById(Long.parseLong(bisOrderZhid));
        Optional<Snry> byId1 = snryRepository.findById(byId.get().getBisZhsqSnryId());

        // 订单经纬度
        double hljgLongitude =Double.parseDouble(ordjd);
        double hljgLatitude = Double.parseDouble(ordwd);
        System.out.println(hljgLongitude +"-"+hljgLatitude);
        // 失能人员经纬度
        double snryLongitude =Double.parseDouble(byId1.get().getBisSnryJd());
        double snryLatitude = Double.parseDouble(byId1.get().getBisSnryWd());

        Map<String, String> map = DistanceUtil.getDistance(snryLongitude, snryLatitude, hljgLongitude, hljgLatitude);
        double distance = Double.parseDouble(map.get("meter"));
        // 位置大于200米
        if(distance > 200){
            map.put("msg","当前定位距离过远！");
            return map;
        }
        return map;
    }

}